namespace Tnelab{
    export function GetRandomNum(Min: number, Max: number): Number {
        var Range = Max - Min;
        var Rand = Math.random();
        return (Min + Math.round(Rand * Range));
    }
    export function GetUtf8OneSize(c: number): number {
        // 0xxxxxxx 返回0
        // 10xxxxxx 不存在
        // 110xxxxx 返回2
        // 1110xxxx 返回3
        // 11110xxx 返回4
        // 111110xx 返回5
        // 1111110x 返回6
        if (c < 0x80) return 0;
        if (c >= 0x80 && c < 0xC0) return -1;
        if (c >= 0xC0 && c < 0xE0) return 2;
        if (c >= 0xE0 && c < 0xF0) return 3;
        if (c >= 0xF0 && c < 0xF8) return 4;
        if (c >= 0xF8 && c < 0xFC) return 5;
        if (c >= 0xFC) return 6;
    }
    export function Utf8OneBytesToUnicodeCode(dv: DataView, position: { Offset: number }): number {
        // b1 表示UTF-8编码的pInput中的高字节, b2 表示次高字节, ...
        let b1, b2, b3, b4, b5, b6;

        let unic = new Uint8Array(4);
        let utfbytes = Tnelab.GetUtf8OneSize(dv.getUint8(position.Offset));

        switch (utfbytes) {
            case 0:
                unic[0] = dv.getUint8(position.Offset);
                utfbytes += 1;
                break;
            case 2:
                b1 = dv.getUint8(position.Offset);
                b2 = dv.getUint8(position.Offset + 1);
                if ((b2 & 0xE0) != 0x80)
                    return 0;
                unic[0] = (b1 << 6) + (b2 & 0x3F);
                unic[1] = (b1 >> 2) & 0x07;
                break;
            case 3:
                b1 = dv.getUint8(position.Offset);
                b2 = dv.getUint8(position.Offset + 1);
                b3 = dv.getUint8(position.Offset + 2);
                if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80))
                    return 0;
                unic[0] = (b2 << 6) + (b3 & 0x3F);
                unic[1] = (b1 << 4) + ((b2 >> 2) & 0x0F);
                break;
            case 4:
                b1 = dv.getUint8(position.Offset);
                b2 = dv.getUint8(position.Offset + 1);
                b3 = dv.getUint8(position.Offset + 2);
                b4 = dv.getUint8(position.Offset + 3);
                if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)
                    || ((b4 & 0xC0) != 0x80))
                    return 0;
                unic[0] = (b3 << 6) + (b4 & 0x3F);
                unic[1] = (b2 << 4) + ((b3 >> 2) & 0x0F);
                unic[2] = ((b1 << 2) & 0x1C) + ((b2 >> 4) & 0x03);
                break;
            case 5:
                b1 = dv.getUint8(position.Offset);
                b2 = dv.getUint8(position.Offset + 1);
                b3 = dv.getUint8(position.Offset + 2);
                b4 = dv.getUint8(position.Offset + 3);
                b5 = dv.getUint8(position.Offset + 4);
                if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)
                    || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80))
                    return 0;
                unic[0] = (b4 << 6) + (b5 & 0x3F);
                unic[1] = (b3 << 4) + ((b4 >> 2) & 0x0F);
                unic[2] = (b2 << 2) + ((b3 >> 4) & 0x03);
                unic[3] = (b1 << 6);
                break;
            case 6:
                b1 = dv.getUint8(position.Offset);
                b2 = dv.getUint8(position.Offset + 1);
                b3 = dv.getUint8(position.Offset + 2);
                b4 = dv.getUint8(position.Offset + 3);
                b5 = dv.getUint8(position.Offset + 4);
                b6 = dv.getUint8(position.Offset + 5);
                if (((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80)
                    || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80)
                    || ((b6 & 0xC0) != 0x80))
                    return 0;
                unic[0] = (b5 << 6) + (b6 & 0x3F);
                unic[1] = (b5 << 4) + ((b6 >> 2) & 0x0F);
                unic[2] = (b3 << 2) + ((b4 >> 4) & 0x03);
                unic[3] = ((b1 << 6) & 0x40) + (b2 & 0x3F);
                break;
            default:
                return 0;
        }
        position.Offset += utfbytes;
        let view = new DataView(unic.buffer);
        return view.getUint32(0, true);
    }
    export function UnicodeOne2Utf8Bytes(unic: number): Uint8Array {
        let bytes = new Uint8Array(6);
        let bytesSize = 0;
        if (unic <= 0x0000007F) {
            // * U-00000000 - U-0000007F:  0xxxxxxx
            bytes[0] = (unic & 0x7F);
            bytesSize = 1;
        }
        else if (unic >= 0x00000080 && unic <= 0x000007FF) {
            // * U-00000080 - U-000007FF:  110xxxxx 10xxxxxx
            bytes[1] = (unic & 0x3F) | 0x80;
            bytes[0] = ((unic >> 6) & 0x1F) | 0xC0;
            bytesSize = 2;
        }
        else if (unic >= 0x00000800 && unic <= 0x0000FFFF) {
            // * U-00000800 - U-0000FFFF:  1110xxxx 10xxxxxx 10xxxxxx
            bytes[2] = (unic & 0x3F) | 0x80;
            bytes[1] = ((unic >> 6) & 0x3F) | 0x80;
            bytes[0] = ((unic >> 12) & 0x0F) | 0xE0;
            bytesSize = 3;
        }
        else if (unic >= 0x00010000 && unic <= 0x001FFFFF) {
            // * U-00010000 - U-001FFFFF:  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
            bytes[3] = (unic & 0x3F) | 0x80;
            bytes[2] = ((unic >> 6) & 0x3F) | 0x80;
            bytes[1] = ((unic >> 12) & 0x3F) | 0x80;
            bytes[0] = ((unic >> 18) & 0x07) | 0xF0;
            bytesSize = 4;
        }
        else if (unic >= 0x00200000 && unic <= 0x03FFFFFF) {
            // * U-00200000 - U-03FFFFFF:  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
            bytes[4] = (unic & 0x3F) | 0x80;
            bytes[3] = ((unic >> 6) & 0x3F) | 0x80;
            bytes[2] = ((unic >> 12) & 0x3F) | 0x80;
            bytes[1] = ((unic >> 18) & 0x3F) | 0x80;
            bytes[0] = ((unic >> 24) & 0x03) | 0xF8;
            bytesSize = 5;
        }
        else if (unic >= 0x04000000 && unic <= 0x7FFFFFFF) {
            // * U-04000000 - U-7FFFFFFF:  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
            bytes[5] = (unic & 0x3F) | 0x80;
            bytes[4] = ((unic >> 6) & 0x3F) | 0x80;
            bytes[3] = ((unic >> 12) & 0x3F) | 0x80;
            bytes[2] = ((unic >> 18) & 0x3F) | 0x80;
            bytes[1] = ((unic >> 24) & 0x3F) | 0x80;
            bytes[0] = ((unic >> 30) & 0x01) | 0xFC;
            bytesSize = 6;
        }
        let u8Array = new Uint8Array(bytesSize);
        for (let i = 0; i < bytesSize; i++) {
            u8Array[i] = bytes[i];
        }
        return u8Array;
    }
}
